/**
 * 
 */
package ca.lscs.web;

import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;

import com.google.appengine.repackaged.org.json.JSONArray;
import com.google.appengine.repackaged.org.json.JSONException;
import com.google.appengine.repackaged.org.json.JSONObject;
import com.googlecode.objectify.Key;

import ca.lscs.dal.ChecklistDao;
import ca.lscs.dal.UserDao;
import ca.lscs.model.AppUser;
import ca.lscs.model.Checklist;
import ca.lscs.model.ChecklistGroup;
import ca.lscs.model.ChecklistItem;
import ca.lscs.model.ChecklistState;
import ca.lscs.model.UserType;
import ca.lscs.web.utils.SessionUtils;

/**
 * @author Steve Pennington
 *
 */
@Controller
@SessionAttributes(value = { SessionUtils.USER_SESSION_KEY }, types = { AppUser.class })
public class ChecklistController {
	
	@RequestMapping(value="/checklist/{id}", method=RequestMethod.GET)
	public ModelAndView handleView(HttpServletRequest request, HttpServletResponse response,
			@PathVariable("id") String checklistId) throws IOException {
		try {
			long id = Long.parseLong(checklistId);
			ChecklistDao checklistDao = ChecklistDao.getInstance();
			Checklist checklist = checklistDao.getById(id);
			
			HashMap<Long, List<ChecklistItem>> groupItemMap =  new HashMap<Long, List<ChecklistItem>>();
			List<ChecklistGroup> groups = checklistDao.getChecklistGroups();
			List<ChecklistItem> groupItems;
			for(ChecklistGroup group : groups) {
				groupItems = checklistDao.getChecklistItems(group);
				groupItemMap.put(group.getId(), groupItems);
			}
			
			Map<String, Object> model = new HashMap<String, Object>();
			model.put("groups", groups);
			model.put("groupItems", groupItemMap);
			model.put("checklist", checklist);
			
			return new ModelAndView("viewchecklist", model);
		} catch(NumberFormatException e) {
			response.sendRedirect("/");
			return null;
		}
	}
	
	@RequestMapping(value="/checklist/{id}", method=RequestMethod.POST)
	public void doUpdate(HttpServletRequest request, HttpServletResponse response,
			@PathVariable("id") String checklistId) throws IOException {
		try {
			long id = Long.parseLong(checklistId);
			ChecklistDao checklistDao = ChecklistDao.getInstance();
			Checklist checklist = checklistDao.getById(id);
			
			List<ChecklistItem> itemKeys = checklistDao.getChecklistItems();
			for(ChecklistItem item : itemKeys) {
				try {
					String stateStr = ServletRequestUtils.getStringParameter(request, Long.toString(item.getId()));
					ChecklistState state = ChecklistState.valueOf(stateStr);
					checklist.setItemState(new Key<ChecklistItem>(ChecklistItem.class, item.getId()), state);
				} catch(Exception e) {
					//Invalid parameter just skip it
				}
			}
			
			checklistDao.put(checklist);
		} catch(NumberFormatException e) {
			//Invalid checklist ID. Just redirect to home page
		}
		
		response.sendRedirect("/");
	}
	
	@RequestMapping(value="/checklist/create", method=RequestMethod.GET)
	public ModelAndView handleCreate() {
		UserDao userDao = UserDao.getInstance();
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("surveyors", userDao.getByType(UserType.SURVEYOR));
		return new ModelAndView("createchecklist", model);
	}
	
	private Checklist parseFromRequest(HttpServletRequest request, Checklist checklist, AppUser user) throws ServletRequestBindingException {
		String title = ServletRequestUtils.getRequiredStringParameter(request, "title");
		String description = ServletRequestUtils.getRequiredStringParameter(request, "description");
		String fileNumber = ServletRequestUtils.getRequiredStringParameter(request, "filenumber");
		String landDistrict = ServletRequestUtils.getRequiredStringParameter(request, "landdistrict");
		String address = ServletRequestUtils.getRequiredStringParameter(request, "address");
		long asigneeId = ServletRequestUtils.getRequiredLongParameter(request, "asignee");
		
		Key<AppUser> asigneeKey = new Key<AppUser>(AppUser.class, asigneeId);
		UserDao userDao = UserDao.getInstance();
		AppUser asignee = userDao.get(asigneeKey);
		
		checklist.setAddress(address);
		checklist.setAsignee(asignee);
		checklist.setCreatedDate(Calendar.getInstance().getTime());
		checklist.setCreator(user);
		checklist.setDescription(description);
		checklist.setFileNumber(fileNumber);
		checklist.setLandDistrict(landDistrict);
		checklist.setSubmitted(false);
		checklist.setTitle(title);
		
		return checklist;
	}
	
	@RequestMapping(value="/checklist/create", method=RequestMethod.POST)
	public ModelAndView doCreate(HttpServletRequest request, HttpServletResponse response,
			@ModelAttribute(SessionUtils.USER_SESSION_KEY) AppUser user) throws IOException {
		try {
			Checklist checklist = parseFromRequest(request, new Checklist(), user);
			ChecklistDao checklistDao = ChecklistDao.getInstance();
			checklistDao.put(checklist);
			response.sendRedirect("/");
			return null;
		} catch(ServletRequestBindingException e) {
			return handleCreate();
		}
	}
	
	@RequestMapping(value="/checklist/edit/{checklistId}", method=RequestMethod.GET)
	public ModelAndView handleEdit(HttpServletResponse response,
			@PathVariable("checklistId") String checklistId) throws IOException {
		try {
			UserDao userDao = UserDao.getInstance();
			long id = Long.parseLong(checklistId);
			ChecklistDao checklistDao = ChecklistDao.getInstance();
			Checklist checklist = checklistDao.getById(id);
			
			if(checklist == null) {
				throw new IllegalArgumentException();
			}
			
			Map<String, Object> model = new HashMap<String, Object>();
			model.put("surveyors", userDao.getByType(UserType.SURVEYOR));
			model.put("checklist", checklist);
			
			return new ModelAndView("editchecklist", model);
		} catch(Exception e) {
			response.sendRedirect("/");
			return null;
		}
	}
	
	@RequestMapping(value="/checklist/edit/{checklistId}", method=RequestMethod.POST)
	public ModelAndView doEdit(HttpServletRequest request, HttpServletResponse response,
			@PathVariable("checklistId") String checklistId, @ModelAttribute(SessionUtils.USER_SESSION_KEY) AppUser user) throws IOException {
		try {		
			long id = Long.parseLong(checklistId);
			ChecklistDao checklistDao = ChecklistDao.getInstance();
			Checklist checklist = checklistDao.getById(id);
			
			if(checklist != null) {
				checklist = parseFromRequest(request, checklist, user);
				checklistDao.put(checklist);
			}
			
			response.sendRedirect("/checklist/" + checklistId);
		} catch(Exception e) {
			response.sendRedirect("/checklist/edit/" + checklistId);
		}
		
		return null;
	}
	
	@RequestMapping(value="/ajax/checklists/assigned", method=RequestMethod.GET)
	public void handleAjaxAssigned(HttpServletRequest request, HttpServletResponse response,
			@ModelAttribute(SessionUtils.USER_SESSION_KEY) AppUser user) throws IOException {
		ChecklistDao checklistDao = ChecklistDao.getInstance();
		List<Checklist> checklists = null;
		if(user.getType() == UserType.SURVEYOR) {
			checklists = checklistDao.getOpenByAsignee(user);
		} else if(user.getType() == UserType.MANAGER) {
			checklists = checklistDao.getOpenByCreator(user);
		}
		
		try {
			JSONArray jArray = new JSONArray();
			JSONObject jChecklist;
			for(Checklist checklist : checklists) {
				jChecklist = new JSONObject();
				jChecklist.put("id", checklist.getId());
				jChecklist.put("title", checklist.getTitle());
				jChecklist.put("description", checklist.getDescription());
				jChecklist.put("date", checklist.getCreatedDate());
				jArray.put(jChecklist);
			}
			response.setContentType("application/json");
			response.getWriter().write(jArray.toString());
		} catch (JSONException e) {
			response.setContentType("application/json");
			response.getWriter().write("{error:'" + e.getMessage() + "'}");
		}
	}
	
	@RequestMapping(value="/ajax/checklists/submitted", method=RequestMethod.GET)
	public void handleAjaxSubmitted(HttpServletRequest request, HttpServletResponse response,
			@ModelAttribute(SessionUtils.USER_SESSION_KEY) AppUser user) throws IOException {
		ChecklistDao checklistDao = ChecklistDao.getInstance();
		List<Checklist> checklists = null;
		if(user.getType() == UserType.SURVEYOR) {
			checklists = checklistDao.getSubmittedByAsignee(user);
		} else if(user.getType() == UserType.MANAGER) {
			checklists = checklistDao.getSubmittedByCreator(user);
		}
		
		try {
			JSONArray jArray = new JSONArray();
			JSONObject jChecklist;
			for(Checklist checklist : checklists) {
				jChecklist = new JSONObject();
				jChecklist.put("id", checklist.getId());
				jChecklist.put("title", checklist.getTitle());
				jChecklist.put("description", checklist.getDescription());
				jChecklist.put("date", checklist.getCreatedDate());
				jArray.put(jChecklist);
			}
			response.setContentType("application/json");
			response.getWriter().write(jArray.toString());
		} catch (JSONException e) {
			response.setContentType("application/json");
			response.getWriter().write("{error:'" + e.getMessage() + "'}");
		}
	}
	
	@RequestMapping(value="/ajax/checklist/submit", method=RequestMethod.POST)
	public void handleAjaxDoSubmit(HttpServletRequest request, HttpServletResponse response,
			@ModelAttribute(SessionUtils.USER_SESSION_KEY) AppUser user) throws IOException {
		try {
			String[] ids = ServletRequestUtils.getRequiredStringParameters(request, "ids");
			ChecklistDao checklistDao = ChecklistDao.getInstance();
			long checklistId;
			Checklist checklist;
			JSONArray jResponse = new JSONArray();
			
			for(String id : ids) {
				checklistId = Long.parseLong(id);
				checklist = checklistDao.getById(checklistId);
				if(checklist != null && checklist.isSubmitted() == false &&
						checklist.getAsignee().getId() == user.getId()) {
					checklist.setSubmitted(true);
					checklistDao.put(checklist);
					jResponse.put(checklistId);
				}
			}
			
			response.setContentType("application/json");
			response.getWriter().write(jResponse.toString());
		} catch (ServletRequestBindingException e) {
			response.setContentType("application/json");
			response.getWriter().write("{error:'" + e.getMessage() + "'}");
		}
		
	}
	
	@RequestMapping(value="/ajax/checklist/delete", method=RequestMethod.POST)
	public void handleAjaxDoDelete(HttpServletRequest request, HttpServletResponse response,
			@ModelAttribute(SessionUtils.USER_SESSION_KEY) AppUser user) throws IOException {
		try {
			String[] ids = ServletRequestUtils.getRequiredStringParameters(request, "ids");
			ChecklistDao checklistDao = ChecklistDao.getInstance();
			long checklistId;
			Checklist checklist;
			JSONArray jResponse = new JSONArray();
			
			for(String id : ids) {
				checklistId = Long.parseLong(id);
				checklist = checklistDao.getById(checklistId);
				if(checklist != null && checklist.getCreator().getId() == user.getId()) {
					checklistDao.delete(checklist);
					jResponse.put(checklistId);
				}
			}
			
			response.setContentType("application/json");
			response.getWriter().write(jResponse.toString());
		} catch (ServletRequestBindingException e) {
			response.setContentType("application/json");
			response.getWriter().write("{error:'" + e.getMessage() + "'}");
		}
		
	}
}
